#pragma once

#include <string>
#include "api/peer_connection_interface.h"
#include "api/scoped_refptr.h"
#include "api/media_stream_interface.h"
#include "pc/stream_collection.h"
#include "rtc_client/nativecpp/peer_connection_dependency_factory_native.h"
#include "rtc_client/observer/functional_observer.h"
#include "rtc_client/rtc_wrapper.h"

namespace ohosrtc {

class SignalingClient;
using PeerConnectionObserver = webrtc::PeerConnectionObserver;
using OnAddMediaStreamEvent = std::function<void(MediaStreamPtr stream)>;
using OnRemoveMediaStreamEvent = std::function<void(MediaStreamPtr stream)>;

//webrtc peer_connection wrapper
class PeerConnectionChannelNative : public PeerConnectionObserver, public std::enable_shared_from_this<PeerConnectionChannelNative>  {
  public:
    explicit PeerConnectionChannelNative(PeerConnectionChannelConfiguration configuration, 
            std::shared_ptr<PeerConnectionDependencyFactoryNative> pcd_factory,
            std::shared_ptr<SignalingClient> signaling_client);
    ~PeerConnectionChannelNative();
  
    static std::shared_ptr<PeerConnectionChannelNative> Create(PeerConnectionChannelConfiguration configuration, 
            std::shared_ptr<PeerConnectionDependencyFactoryNative> pcd_factory,
            std::shared_ptr<SignalingClient> signaling_client);
    //use to make call
    void CreateP2pOffer(LocalStreamPtr ohos_local_stream);
    //use to accept call
    void CreateP2pAnswer(LocalStreamPtr local_stream);
    //handle pc close
    void Close();
    // add stream to pc
    void AddStream(MediaStreamPtr media_stream);
    // remove stream to pc
    void RemoveStream(MediaStreamPtr media_stream);
    // sdp process
    void CreateOffer();
    // sdp process
    void CreateAnswer();
    // sdp process
    void SetLocalDescription(SDP* desc);
    // sdp process
    void SetRemoteDescription(SDP* desc);
    void SetRemoteIceCandidate(IceCandidate* ice_candidate);
    // set stream event handler
	  void SetStreamEventHandler(OnAddMediaStreamEvent onAddStream, OnRemoveMediaStreamEvent onRemoveStream);
  
    // pc sdp event observer
    void OnCreateSdpSuccess(SDP *desc);
    void OnCreateSdpFailure(const std::string error);
    void OnSetLocalSdpCompletion(const webrtc::RTCError error);
    void OnSetRemoteSdpCompletion(const webrtc::RTCError error);
  
    // Implements PeerConnectionObserver. Triggered when the SignalingState changed.
    void OnSignalingChange(SignalingState new_state) override;

    // Implements PeerConnectionObserver. Triggered when media is received on a new stream from remote peer.
    void OnAddStream(MediaStreamPtr stream) override;

    // Implements PeerConnectionObserver. Triggered when a remote peer closes a stream.
    void OnRemoveStream(MediaStreamPtr stream) override;

    // Implements PeerConnectionObserver. Triggered when a remote peer opens a data channel.
    void OnDataChannel(DataChannelPtr data_channel) override;
  
    // Implements PeerConnectionObserver. Called any time the IceGatheringState changes.
    void OnIceGatheringChange(IceGatheringState new_state) override ;

    // Implements PeerConnectionObserver. A new ICE candidate has been gathered.
    void OnIceCandidate(const IceCandidate* candidate) override ;
    
    void OnIceConnectionChange(IceConnectionState new_state) override;
    
    void OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
                    const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> &streams) override;
  
    // set local stream for pc and save private ohos_local_stream_
    void setLocalStream(LocalStreamPtr stream);
    PeerConnectionPtr GetPeerConnection();
    std::weak_ptr<PeerConnectionChannelNative> weak_this_;
    std::string id;
  
  private:
    void InitPeerConnection();
    FunctionalCreateSdpObserver *MakeCreateSdpObserver(const std::weak_ptr<PeerConnectionChannelNative> &weak_this);
    rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface> MakeSetLocalDescriptionObserver(const std::weak_ptr<PeerConnectionChannelNative> &weak_this);
    rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> MakeSetRemoteDescriptionObserver(const std::weak_ptr<PeerConnectionChannelNative> &weak_this);
    PeerConnectionChannelConfiguration configuration_;
    PeerConnectionPtr peer_connection_;
    LocalStreamPtr local_stream_;
    std::shared_ptr<PeerConnectionDependencyFactoryNative> pcd_factory_;
    std::shared_ptr<SignalingClient> signaling_client_;
	  OnAddMediaStreamEvent on_add_stream_event_;
	  OnRemoveMediaStreamEvent on_remove_stream_event_;
    std::unordered_map<std::string, std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>>> stream_sends_;
};

} // namespace ohosrtc